#include <Messenger.h>
const long X = 3; //for demo purpose, increasing x, results in reducing the frequency of changes in projects setup
const long interval = 3000/X; //in microseconds.
const int SCK = 8;
const int DATA = 9;

int counter =0;




const int projectNumber = 4;
struct project{
  int  leds[3];
};

project projects[projectNumber];

// Instantiate Messenger object with the message function and the default separator (the space character)
Messenger message = Messenger(); 

void setupProjects(){
  int version=counter%5;
  
  if(version==0){
    for(int i=0;i<projectNumber;++i)
      for(int j=0;j<3;++j){
        projects[i].leds[j]=0;
      }
  }
  else if(version==1){
      for(int i=0;i<projectNumber;++i)
      for(int j=0;j<3;++j){
        if(j==0){
          projects[i].leds[j]=0x1F;
        }else
          projects[i].leds[j]=0;
      }
  }

  else if(version==2){
      for(int i=0;i<projectNumber;++i)
      for(int j=0;j<3;++j){
                if(j==1){
          projects[i].leds[j]=0x1F;
        }else
          projects[i].leds[j]=0;
      }
  }

  else if(version==3){
      for(int i=0;i<projectNumber;++i)
      for(int j=0;j<3;++j){
               if(j==2){
          projects[i].leds[j]=0x1F;
        }else
          projects[i].leds[j]=0;
      }
  }
  else{
     for(int i=0;i<projectNumber;++i)
      for(int j=0;j<3;++j){
        projects[i].leds[j]=0x1F;
  }
 }
  

++counter;
}


// Define messenger function
void messageCompleted() {
    int group = message.readInt();
    int led = message.readInt();
    int bright = message.readInt();
    set(group,led,bright);
 /*
    Serial.print("grupa: ");
    Serial.print(group);
    Serial.print(",dioda: ");
    Serial.print(led);
    Serial.print(",jasnosc: ");
    Serial.print(bright);
    Serial.print("\n");  
    
    */
}

// Set leds value in ***PROGRAM**
void set(int group, int led, int bright){
projects[group].leds[led]=bright;
}


void sendBit(boolean b){
 digitalWrite(SCK,LOW);
 digitalWrite(DATA,b);
 if(interval<16000){
   delayMicroseconds(interval);
   digitalWrite(SCK,HIGH);
   delayMicroseconds(interval);
/*Currently, the largest value that will produce an accurate delay is 16383.
This could change in future Arduino releases.
For delays longer than a few thousand microseconds, you should use delay() instead. */   
 }else{
   int intervalMili=interval/1000;
   delay(intervalMili);
   digitalWrite(SCK,HIGH);
   delay(intervalMili);
 
 }
}

void sendSync(){
    for(int i=0;i<16;++i){
   sendBit(LOW);
  }
}

void sendGroup(int g){
  for(int led=0;led<3;++led){
    sendBit(HIGH);
    sendBit(LOW);
    for(int mask=0x20;mask>0;mask>>=1){
      if(g & mask){
        sendBit(HIGH);
      }else{
        sendBit(LOW);
      }
    }
    sendBit(HIGH);
    for(int mask=0x2;mask>0;mask>>=1){
      if(led & mask){
        sendBit(HIGH);
      }else{
        sendBit(LOW);
      }
    }
        for(int mask=0x10;mask>0;mask>>=1){
      if(projects[g].leds[led] & mask){
        sendBit(HIGH);
      }else{
        sendBit(LOW);
      }
    }
    
  }
}

//send message to devices
void send(){
  sendSync();
  

  
  for(int i=0;i<projectNumber;++i){
      sendGroup(i);
     sendSync();
  }
  
  
        
}



void setup() {
  pinMode(SCK, OUTPUT); 
  pinMode(DATA, OUTPUT); 
  
  // Initiate Serial Communication
  Serial.begin(9600); 
  for(int i=8;i<14;++i){
    pinMode(i, OUTPUT);
  }

  
  message.attach(messageCompleted);
}

void loop() {
  // The following line is the most effective way of 
  // feeding the serial data to Messenger
  while ( Serial.available( ) ) message.process(Serial.read( ) );
 //setupProjects();
  for(int i=0;i<X;++i){
    send();
  }

 }





